<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<!-- 
	Copyright (C) 2007, 2008, 2009, 2010, 2011. PARP Research Group.
	<http://perception.inf.um.es>
	University of Murcia, Spain.

	This file is part of the QVision library.

	QVision is free software: you can redistribute it and/or modify
	it under the terms of the GNU Lesser General Public License as
	published by the Free Software Foundation, version 3 of the License.

	QVision is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU Lesser General Public License for more details.

	You should have received a copy of the GNU Lesser General Public
	License along with QVision. If not, see <http://www.gnu.org/licenses/>.
-->

<html><head><meta http-equiv="content-Type" content="text/html;charset=UTF-8">
<title>QVision: Qt&#39;s Image, Video and Computer Vision Library</title>
<meta name="title" content="QVision" />
<meta name="dc.title" content="QVision" />
<meta name="url" content="http://perception.inf.um.es/QVision" />
<meta name="author" content="PARP Research Group - http://perception.inf.um.es" />
<meta name="revisit-after" content="30 DAYS"/>
<meta name="robots" content="index,follow"/>
<meta name="classification" content="*">
<meta name="rating" content="Safe For Kids">
<meta name="distribution" content="GLOBAL"/>
<meta name="description" content="Qt's Image, Video and Computer Vision Library"/>
<meta name="page-topic" content="Computer Vision research and prototype programming"/>
<meta name="geo.country" content="ES" />

<!--
Keywords:
By license:		open source, gnu, lgpl, gpl, free
By theme:		computer vision, image processing, robotics, programming, source, development
By usage:		library, toolkit, framework, prototype, application
By programming specs:	object oriented, c++, block programming, reusability, gui, graphical, parallel computing, high performance, GPU, prototyping
Interoperability with:	Qt, GSL, GNU Scientific library, OpenCV, CGAL, QWT, CUDA, mplayer, IPP, Intel Image Performance Primitives, blas, lapack
Functionallity:		image features, matrix algebra, projective geometry, mser, function minimization, function optimization, canny operator, harris operator, corner detection, performance evaluation, cpu usage, graphical interface
Main data-types:	matrix, vector, tensor, quaternion, image, polyline
Video sources:		webcam, camera, stream
Devices:		embedded, desktop computer, laptop, mini-laptop
Authors:		PARP research group. University of Murcia, Spain.
-->

<meta name="keywords" content="augmented reality, sfm, structure from motion, open source, gnu, lgpl, gpl, free, computer vision, image processing, robotics, programming, source, development, library, toolkit, framework, prototype, application, object oriented, c++, block programming, reusability, gui, graphical, parallel computing, high performance, GPU, prototyping, Qt, GSL, GNU Scientific library, OpenCV, CGAL, QWT, CUDA, mplayer, IPP, Intel Image Performance Primitives, blas, lapack, image features, matrix algebra, projective geometry, mser, function minimization, function optimization, canny operator, harris operator, corner detection, performance evaluation, cpu usage, graphical interface, matrix, vector, tensor, quaternion, image, polyline, webcam, camera, stream, embedded, desktop computer, laptop, mini-laptop, University of Murcia, Spain, PARP research group, vision por computador"/>
<meta http-equiv="keywords" content="augmented reality, sfm, structure from motion, open source, gnu, lgpl, gpl, free, computer vision, image processing, robotics, programming, source, development, library, toolkit, framework, prototype, application, object oriented, c++, block programming, reusability, gui, graphical, parallel computing, high performance, GPU, prototyping, Qt, GSL, GNU Scientific library, OpenCV, CGAL, QWT, CUDA, mplayer, IPP, Intel Image Performance Primitives, blas, lapack, image features, matrix algebra, projective geometry, mser, function minimization, function optimization, canny operator, harris operator, corner detection, performance evaluation, cpu usage, graphical interface, matrix, vector, tensor, quaternion, image, polyline, webcam, camera, stream, embedded, desktop computer, laptop, mini-laptop, University of Murcia, Spain, PARP research group, vision por computador"/>
<meta http-equiv="pragma" content="no-cache"/>
<meta http-equiv="title" content="QVision"/>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
<link href="tabs.css" rel="stylesheet" type="text/css" />
<link rel="shortcut icon" href="favicon.ico" />
</head><body>

<table width="100%"><tr>
	<td><a href="http://perception.inf.um.es/"><img src="parp.png" border="0" /> <big>PARP Research Group</big></a></td>
	<td align="right"><a href="http://www.um.es/"><big>Universidad de Murcia</big> <img src="um.png" border="0" /></a></td>
</tr></table>

<hr /><br />

<table width="95%" align="center"><tr><td>

<!-- Generated by Doxygen 1.6.3 -->
<script type="text/javascript"><!--
var searchBox = new SearchBox("searchBox", "search",false,'Search');
--></script>
<div class="navigation" id="top">
  <div class="tabs">
    <ul>
      <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
      <li><a href="pages.html"><span>Related&nbsp;Pages</span></a></li>
      <li><a href="modules.html"><span>Modules</span></a></li>
      <li><a href="annotated.html"><span>Classes</span></a></li>
      <li class="current"><a href="files.html"><span>Files</span></a></li>
      <li>
        <div id="MSearchBox" class="MSearchBoxInactive">
          <form id="FSearchBox" action="search.php" method="get">
            <img id="MSearchSelect" src="search/search.png" alt=""/>
            <input type="text" id="MSearchField" name="query" value="Search" size="20" accesskey="S" 
                   onfocus="searchBox.OnSearchFieldFocus(true)" 
                   onblur="searchBox.OnSearchFieldFocus(false)"/>
          </form>
        </div>
      </li>
    </ul>
  </div>
  <div class="tabs">
    <ul>
      <li><a href="files.html"><span>File&nbsp;List</span></a></li>
      <li><a href="globals.html"><span>File&nbsp;Members</span></a></li>
    </ul>
  </div>
<h1>examples/OpenCV/cameraCalibrator/cameraCalibrator.cpp</h1><a href="cameraCalibrator_8cpp.html">Go to the documentation of this file.</a><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/*</span>
<a name="l00002"></a>00002 <span class="comment"> *      Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012. PARP Research Group.</span>
<a name="l00003"></a>00003 <span class="comment"> *      &lt;http://perception.inf.um.es&gt;</span>
<a name="l00004"></a>00004 <span class="comment"> *      University of Murcia, Spain.</span>
<a name="l00005"></a>00005 <span class="comment"> *</span>
<a name="l00006"></a>00006 <span class="comment"> *      This file is part of the QVision library.</span>
<a name="l00007"></a>00007 <span class="comment"> *</span>
<a name="l00008"></a>00008 <span class="comment"> *      QVision is free software: you can redistribute it and/or modify</span>
<a name="l00009"></a>00009 <span class="comment"> *      it under the terms of the GNU Lesser General Public License as</span>
<a name="l00010"></a>00010 <span class="comment"> *      published by the Free Software Foundation, version 3 of the License.</span>
<a name="l00011"></a>00011 <span class="comment"> *</span>
<a name="l00012"></a>00012 <span class="comment"> *      QVision is distributed in the hope that it will be useful,</span>
<a name="l00013"></a>00013 <span class="comment"> *      but WITHOUT ANY WARRANTY; without even the implied warranty of</span>
<a name="l00014"></a>00014 <span class="comment"> *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span>
<a name="l00015"></a>00015 <span class="comment"> *      GNU Lesser General Public License for more details.</span>
<a name="l00016"></a>00016 <span class="comment"> *</span>
<a name="l00017"></a>00017 <span class="comment"> *      You should have received a copy of the GNU Lesser General Public</span>
<a name="l00018"></a>00018 <span class="comment"> *      License along with QVision. If not, see &lt;http://www.gnu.org/licenses/&gt;.</span>
<a name="l00019"></a>00019 <span class="comment"> */</span>
<a name="l00020"></a>00020 
<a name="l00048"></a>00048 <span class="preprocessor">#include &lt;iostream&gt;</span>
<a name="l00049"></a>00049 <span class="preprocessor">#include &lt;fstream&gt;</span>
<a name="l00050"></a>00050 
<a name="l00051"></a>00051 <span class="preprocessor">#include &lt;QVMatrix&gt;</span>
<a name="l00052"></a>00052 <span class="preprocessor">#include &lt;QVApplication&gt;</span>
<a name="l00053"></a>00053 <span class="preprocessor">#include &lt;QVImageCanvas&gt;</span>
<a name="l00054"></a>00054 <span class="preprocessor">#include &lt;QVVideoReaderBlock&gt;</span>
<a name="l00055"></a>00055 <span class="preprocessor">#include &lt;QVDefaultGUI&gt;</span>
<a name="l00056"></a>00056 
<a name="l00057"></a>00057 <span class="preprocessor">#include &lt;qvip.h&gt;</span>
<a name="l00058"></a>00058 <span class="preprocessor">#include &lt;<a class="code" href="qvip_2qvimageio_8h.html" title="File from the QVision library.">qvimageio.h</a>&gt;</span>
<a name="l00059"></a>00059 <span class="preprocessor">#include &lt;qvprojective.h&gt;</span>
<a name="l00060"></a>00060 
<a name="l00061"></a>00061 <span class="preprocessor">#ifndef DOXYGEN_IGNORE_THIS</span>
<a name="l00062"></a>00062 <span class="preprocessor"></span><span class="preprocessor">#include &lt;cv.h&gt;</span>
<a name="l00063"></a>00063 <span class="preprocessor">#include &lt;highgui.h&gt;</span>
<a name="l00064"></a>00064 
<a name="l00065"></a>00065 <span class="preprocessor">#define NUM_CHESSBOARDS 16</span>
<a name="l00066"></a>00066 <span class="preprocessor"></span><span class="comment">/* *************** License:**************************</span>
<a name="l00067"></a>00067 <span class="comment">   Oct. 3, 2008</span>
<a name="l00068"></a>00068 <span class="comment">   Right to use this code in any way you want without warrenty, support or any guarentee of it working.</span>
<a name="l00069"></a>00069 <span class="comment"></span>
<a name="l00070"></a>00070 <span class="comment">   BOOK: It would be nice if you cited it:</span>
<a name="l00071"></a>00071 <span class="comment">   Learning OpenCV: Computer Vision with the OpenCV Library</span>
<a name="l00072"></a>00072 <span class="comment">     by Gary Bradski and Adrian Kaehler</span>
<a name="l00073"></a>00073 <span class="comment">     Published by O&#39;Reilly Media, October 3, 2008</span>
<a name="l00074"></a>00074 <span class="comment"> </span>
<a name="l00075"></a>00075 <span class="comment">   AVAILABLE AT: </span>
<a name="l00076"></a>00076 <span class="comment">     http://www.amazon.com/Learning-OpenCV-Computer-Vision-Library/dp/0596516134</span>
<a name="l00077"></a>00077 <span class="comment">     Or: http://oreilly.com/catalog/9780596516130/</span>
<a name="l00078"></a>00078 <span class="comment">     ISBN-10: 0596516134 or: ISBN-13: 978-0596516130    </span>
<a name="l00079"></a>00079 <span class="comment"></span>
<a name="l00080"></a>00080 <span class="comment">   OTHER OPENCV SITES:</span>
<a name="l00081"></a>00081 <span class="comment">   * The source code is on sourceforge at:</span>
<a name="l00082"></a>00082 <span class="comment">     http://sourceforge.net/projects/opencvlibrary/</span>
<a name="l00083"></a>00083 <span class="comment">   * The OpenCV wiki page (As of Oct 1, 2008 this is down for changing over servers, but should come back):</span>
<a name="l00084"></a>00084 <span class="comment">     http://opencvlibrary.sourceforge.net/</span>
<a name="l00085"></a>00085 <span class="comment">   * An active user group is at:</span>
<a name="l00086"></a>00086 <span class="comment">     http://tech.groups.yahoo.com/group/OpenCV/</span>
<a name="l00087"></a>00087 <span class="comment">   * The minutes of weekly OpenCV development meetings are at:</span>
<a name="l00088"></a>00088 <span class="comment">     http://pr.willowgarage.com/wiki/OpenCV</span>
<a name="l00089"></a>00089 <span class="comment">   ************************************************** */</span>
<a name="l00090"></a>00090 
<a name="l00091"></a>00091 <span class="comment">/*void help()</span>
<a name="l00092"></a>00092 <span class="comment">        {</span>
<a name="l00093"></a>00093 <span class="comment">        std::cout &lt;&lt; &quot;\n\n&quot;</span>
<a name="l00094"></a>00094 <span class="comment">        &quot; Calling convention:\n&quot;</span>
<a name="l00095"></a>00095 <span class="comment">        &quot; ./cameraCalibratorOpenCV  &lt;board_w&gt;  &lt;board_h&gt;  &lt;number_of_boards&gt;  &lt;skip_frames&gt;\n&quot;</span>
<a name="l00096"></a>00096 <span class="comment">        &quot;\n&quot;</span>
<a name="l00097"></a>00097 <span class="comment">        &quot;   WHERE:\n&quot;</span>
<a name="l00098"></a>00098 <span class="comment">        &quot;     board_w, board_h   -- are the number of corners along the row and columns respectively\n&quot;</span>
<a name="l00099"></a>00099 <span class="comment">        &quot;     number_of_boards   -- are the number of chessboard views to collect before calibration\n&quot;</span>
<a name="l00100"></a>00100 <span class="comment">        &quot;     skip_frames        -- are the number of frames to skip before trying to collect another\n&quot;</span>
<a name="l00101"></a>00101 <span class="comment">        &quot;                           good chessboard.  This allows you time to move the chessboard.  \n&quot;</span>
<a name="l00102"></a>00102 <span class="comment">        &quot;                           Move it to many different locations and angles so that calibration \n&quot;</span>
<a name="l00103"></a>00103 <span class="comment">        &quot;                           space will be well covered. \n&quot;</span>
<a name="l00104"></a>00104 <span class="comment">        &quot;\n&quot;</span>
<a name="l00105"></a>00105 <span class="comment">        &quot; Hit ‘p’ to pause/unpause, ESC to quit\n&quot;</span>
<a name="l00106"></a>00106 <span class="comment">        &quot;\n&quot;;</span>
<a name="l00107"></a>00107 <span class="comment">        }*/</span>
<a name="l00108"></a>00108 
<a name="l00109"></a>00109 <span class="keywordtype">double</span>  error(<span class="keyword">const</span> <span class="keywordtype">double</span> u, <span class="keyword">const</span> <span class="keywordtype">double</span> v, <span class="keyword">const</span> <span class="keywordtype">double</span> x, <span class="keyword">const</span> <span class="keywordtype">double</span> y, <span class="keyword">const</span> <a class="code" href="classQVVector.html" title="Implementation of numerical vectors.">QVVector</a> k)
<a name="l00110"></a>00110         {
<a name="l00111"></a>00111         <span class="keyword">const</span> <span class="keywordtype">double</span>    r2 = x*x+y*y, r4 = r2*r2, r6 = r4*r2, r8 = r4*r4,
<a name="l00112"></a>00112                         d = 1 + k[0] * r2 + k[1] * r4 + k[2] * r6 + k[3] * r8;
<a name="l00113"></a>00113         <span class="keyword">const</span> <span class="keywordtype">double</span>    errorU = u - x * d, errorV = v - y * d;
<a name="l00114"></a>00114 
<a name="l00115"></a>00115         <span class="keywordflow">return</span> errorU * errorU + errorV * errorV;
<a name="l00116"></a>00116         }
<a name="l00117"></a>00117 
<a name="l00118"></a>00118 QPointF findMinimum(<span class="keyword">const</span> QPointF &amp;orig, <span class="keyword">const</span> <a class="code" href="classQVVector.html" title="Implementation of numerical vectors.">QVVector</a> k)
<a name="l00119"></a>00119         {
<a name="l00120"></a>00120         <span class="keyword">const</span> <span class="keywordtype">int</span>       u = orig.x(), v = orig.y();
<a name="l00121"></a>00121         QPointF actual = orig;
<a name="l00122"></a>00122 
<a name="l00123"></a>00123         <span class="keywordflow">while</span>(<span class="keyword">true</span>)
<a name="l00124"></a>00124                 {
<a name="l00125"></a>00125                 QPointF best = actual;
<a name="l00126"></a>00126                 <span class="keywordtype">double</span> bestError = std::numeric_limits&lt;double&gt;::max();
<a name="l00127"></a>00127         
<a name="l00128"></a>00128                 <span class="keywordflow">for</span> (<span class="keywordtype">double</span> i = -0.01; i &lt;= 0.01; i+=0.0025)
<a name="l00129"></a>00129                         <span class="keywordflow">for</span> (<span class="keywordtype">double</span> j = -0.01; j &lt;= 0.01; j+=0.0025)
<a name="l00130"></a>00130                                 <span class="keywordflow">if</span> (error(u, v, actual.x()+i, actual.y()+j, k) &lt; bestError)
<a name="l00131"></a>00131                                         best = actual + QPoint(i, j);
<a name="l00132"></a>00132                 <span class="keywordflow">if</span> (actual == best)
<a name="l00133"></a>00133                         <span class="keywordflow">break</span>;
<a name="l00134"></a>00134 
<a name="l00135"></a>00135                 actual = best;
<a name="l00136"></a>00136                 }
<a name="l00137"></a>00137         <span class="keywordflow">return</span> actual;
<a name="l00138"></a>00138         }
<a name="l00139"></a>00139 
<a name="l00140"></a>00140 <span class="keyword">class </span>CameraCalibration
<a name="l00141"></a>00141         {
<a name="l00142"></a>00142         <span class="keyword">public</span>:
<a name="l00143"></a>00143                 <span class="keywordtype">int</span> cols, rows;
<a name="l00144"></a>00144                 <a class="code" href="classQVMatrix.html" title="Implementation of numerical matrices.">QVMatrix</a> K, distortionCoeffs;
<a name="l00145"></a>00145 
<a name="l00146"></a>00146                 <a class="code" href="classQVMatrix.html" title="Implementation of numerical matrices.">QVMatrix</a> Kinv;
<a name="l00147"></a>00147                 IplImage *dx, *dy;
<a name="l00148"></a>00148 
<a name="l00149"></a>00149                 <span class="keywordtype">bool</span> initCacheMap(IplImage *&amp;dx_, IplImage *&amp;dy_, <span class="keyword">const</span> <a class="code" href="classQVMatrix.html" title="Implementation of numerical matrices.">QVMatrix</a> &amp;A2 = <a class="code" href="classQVMatrix.html#a6eb15980d17c17d4a55ab09a77bcd715" title="Creates an identity matrix.">QVMatrix::identity</a>(3))
<a name="l00150"></a>00150                         {
<a name="l00151"></a>00151                         Kinv = <a class="code" href="group__qvmatrixalgebra.html#gadf6472ec782375d465ff1e87b3ae2557" title="Obtains the Moore–Penrose pseudoinverse of a matrix.">pseudoInverse</a>(K);
<a name="l00152"></a>00152 
<a name="l00153"></a>00153                         CvMat   * camera_matrix = K.toCvMat(CV_32F),
<a name="l00154"></a>00154                                 * dist_coeffs = distortionCoeffs.toCvMat(CV_32FC1),
<a name="l00155"></a>00155                                 * new_camera_matrix = A2.toCvMat(CV_32F);
<a name="l00156"></a>00156 
<a name="l00157"></a>00157                         <span class="keywordflow">if</span> (dx_ != NULL)
<a name="l00158"></a>00158                                 cvReleaseImage(&amp;dx);
<a name="l00159"></a>00159                         <span class="keywordflow">if</span> (dy_ != NULL)
<a name="l00160"></a>00160                                 cvReleaseImage(&amp;dy);
<a name="l00161"></a>00161 
<a name="l00162"></a>00162                         <span class="keywordflow">if</span> (cols == 0 or rows == 0)
<a name="l00163"></a>00163                                 <span class="keywordflow">return</span> <span class="keyword">false</span>;
<a name="l00164"></a>00164 
<a name="l00165"></a>00165                         dx_ = cvCreateImage(cvSize(cols, rows), IPL_DEPTH_32F, 1);
<a name="l00166"></a>00166                         dy_ = cvCreateImage(cvSize(cols, rows), IPL_DEPTH_32F, 1);
<a name="l00167"></a>00167 
<a name="l00168"></a>00168                         cvInitUndistortRectifyMap(camera_matrix, dist_coeffs, NULL <span class="comment">/* R */</span>, new_camera_matrix, dx_, dy_);
<a name="l00169"></a>00169 
<a name="l00170"></a>00170                         cvReleaseMat(&amp;camera_matrix);
<a name="l00171"></a>00171                         cvReleaseMat(&amp;dist_coeffs);
<a name="l00172"></a>00172                         cvReleaseMat(&amp;new_camera_matrix);
<a name="l00173"></a>00173 
<a name="l00174"></a>00174                         <span class="keywordflow">return</span> <span class="keyword">true</span>;
<a name="l00175"></a>00175                         }
<a name="l00176"></a>00176 
<a name="l00177"></a>00177         <span class="keyword">public</span>:
<a name="l00178"></a>00178                 CameraCalibration(<span class="keyword">const</span> CameraCalibration &amp;other):
<a name="l00179"></a>00179                         cols(other.cols), rows(other.rows), K(other.K), distortionCoeffs(other.distortionCoeffs), dx(NULL), dy(NULL)
<a name="l00180"></a>00180                         {
<a name="l00181"></a>00181                         initCacheMap(dx, dy);
<a name="l00182"></a>00182                         }
<a name="l00183"></a>00183 
<a name="l00184"></a>00184                 CameraCalibration(      <span class="keyword">const</span> <span class="keywordtype">int</span> cols = 0, <span class="keyword">const</span> <span class="keywordtype">int</span> rows = 0,
<a name="l00185"></a>00185                                         <span class="keyword">const</span> <a class="code" href="classQVMatrix.html" title="Implementation of numerical matrices.">QVMatrix</a> &amp;K = <a class="code" href="classQVMatrix.html#a6eb15980d17c17d4a55ab09a77bcd715" title="Creates an identity matrix.">QVMatrix::identity</a>(3),
<a name="l00186"></a>00186                                         <span class="keyword">const</span> <a class="code" href="classQVMatrix.html" title="Implementation of numerical matrices.">QVMatrix</a> &amp;distortionCoeffs = <a class="code" href="classQVMatrix.html" title="Implementation of numerical matrices.">QVMatrix</a>(4, 1, 0.0)):
<a name="l00187"></a>00187                         cols(cols), rows(rows), K(K), distortionCoeffs(distortionCoeffs), dx(NULL), dy(NULL)
<a name="l00188"></a>00188                         {
<a name="l00189"></a>00189                         initCacheMap(dx,dy);
<a name="l00190"></a>00190                         }
<a name="l00191"></a>00191 
<a name="l00192"></a>00192                 ~CameraCalibration()
<a name="l00193"></a>00193                         {
<a name="l00194"></a>00194                         <span class="keywordflow">if</span> (dx != NULL)
<a name="l00195"></a>00195                                 cvReleaseImage(&amp;dx);
<a name="l00196"></a>00196                         <span class="keywordflow">if</span> (dy != NULL)
<a name="l00197"></a>00197                                 cvReleaseImage(&amp;dy);
<a name="l00198"></a>00198                         }
<a name="l00199"></a>00199 
<a name="l00200"></a>00200                 CameraCalibration &amp; operator = (<span class="keyword">const</span> CameraCalibration &amp;other)
<a name="l00201"></a>00201                         {
<a name="l00202"></a>00202                         cols = other.cols;
<a name="l00203"></a>00203                         rows = other.rows;
<a name="l00204"></a>00204                         K = other.K;
<a name="l00205"></a>00205                         distortionCoeffs = other.distortionCoeffs;
<a name="l00206"></a>00206                         initCacheMap(dx,dy);
<a name="l00207"></a>00207                         <span class="keywordflow">return</span> (*<span class="keyword">this</span>);
<a name="l00208"></a>00208                         }
<a name="l00209"></a>00209 
<a name="l00210"></a>00210                 <span class="keywordtype">bool</span> inited()<span class="keyword"> const</span>
<a name="l00211"></a>00211 <span class="keyword">                        </span>{
<a name="l00212"></a>00212                         <span class="keywordflow">return</span> (cols != 0 and rows != 0);
<a name="l00213"></a>00213                         }
<a name="l00214"></a>00214 
<a name="l00215"></a>00215                 <span class="keywordtype">bool</span> loadFromFile(<span class="keyword">const</span> QString &amp;fileName)
<a name="l00216"></a>00216                         {
<a name="l00217"></a>00217                         std::ifstream stream;
<a name="l00218"></a>00218                         stream.open(qPrintable(fileName));
<a name="l00219"></a>00219 
<a name="l00220"></a>00220                         <span class="keywordflow">if</span> ( stream.fail() )
<a name="l00221"></a>00221                                 <span class="keywordflow">return</span> <span class="keyword">false</span>;
<a name="l00222"></a>00222 
<a name="l00223"></a>00223                         stream &gt;&gt; cols;
<a name="l00224"></a>00224                         stream &gt;&gt; rows;
<a name="l00225"></a>00225                         stream &gt;&gt; K;
<a name="l00226"></a>00226                         stream &gt;&gt; distortionCoeffs;
<a name="l00227"></a>00227 
<a name="l00228"></a>00228                         stream.close();
<a name="l00229"></a>00229 
<a name="l00230"></a>00230                         <span class="keywordflow">return</span> initCacheMap(dx,dy);
<a name="l00231"></a>00231                         }
<a name="l00232"></a>00232 
<a name="l00233"></a>00233                 <span class="keywordtype">bool</span> saveToFile(<span class="keyword">const</span> QString &amp;fileName)<span class="keyword"> const</span>
<a name="l00234"></a>00234 <span class="keyword">                        </span>{
<a name="l00235"></a>00235                         std::ofstream stream;
<a name="l00236"></a>00236                         stream.open(qPrintable(fileName));
<a name="l00237"></a>00237 
<a name="l00238"></a>00238                         <span class="keywordflow">if</span> ( stream.fail() )
<a name="l00239"></a>00239                                 <span class="keywordflow">return</span> <span class="keyword">false</span>;
<a name="l00240"></a>00240 
<a name="l00241"></a>00241                         stream &lt;&lt; cols &lt;&lt; std::endl;
<a name="l00242"></a>00242                         stream &lt;&lt; rows &lt;&lt; std::endl;
<a name="l00243"></a>00243                         stream &lt;&lt; K;
<a name="l00244"></a>00244                         stream &lt;&lt; distortionCoeffs;
<a name="l00245"></a>00245 
<a name="l00246"></a>00246                         stream.close();
<a name="l00247"></a>00247 
<a name="l00248"></a>00248                         <span class="keywordflow">return</span> <span class="keyword">true</span>;
<a name="l00249"></a>00249                         }
<a name="l00250"></a>00250 
<a name="l00251"></a>00251                 QPointF map(<span class="keyword">const</span> <span class="keywordtype">int</span> i, <span class="keyword">const</span> <span class="keywordtype">int</span> j)<span class="keyword"> const</span>
<a name="l00252"></a>00252 <span class="keyword">                        </span>{
<a name="l00253"></a>00253                         <span class="comment">// applyHomography(Kinv,QPointF(i,j))  da mejores resultados que esto. ¿Porqué?</span>
<a name="l00254"></a>00254                         <span class="keywordflow">return</span> QPointF(CV_IMAGE_ELEM(dx, <span class="keywordtype">float</span>, j, i), CV_IMAGE_ELEM(dy, <span class="keywordtype">float</span>, j, i));
<a name="l00255"></a>00255                         }
<a name="l00256"></a>00256 
<a name="l00257"></a>00257                 <a class="code" href="classQVImage.html">QVImage&lt;uChar, 1&gt;</a> radialUndistort(<span class="keyword">const</span> <a class="code" href="classQVImage.html">QVImage&lt;uChar, 1&gt;</a> &amp;image)
<a name="l00258"></a>00258                         {
<a name="l00259"></a>00259                         <span class="keywordflow">if</span> (cols == 0 or rows == 0)
<a name="l00260"></a>00260                                 <span class="keywordflow">return</span> <a class="code" href="classQVImage.html">QVImage&lt;uChar, 1&gt;</a>();
<a name="l00261"></a>00261 
<a name="l00262"></a>00262                         <span class="comment">// --------------</span>
<a name="l00263"></a>00263                         <a class="code" href="classQVMatrix.html" title="Implementation of numerical matrices.">QVMatrix</a> A2 = K;
<a name="l00264"></a>00264                         A2(0,0) = 0.75*A2(0,0);
<a name="l00265"></a>00265                         A2(1,1) = 0.75*A2(1,1);
<a name="l00266"></a>00266                         A2(0,2) = 160.0;
<a name="l00267"></a>00267                         A2(1,2) = 100.0;
<a name="l00268"></a>00268 
<a name="l00269"></a>00269                         IplImage *dx_ = NULL, *dy_ = NULL;
<a name="l00270"></a>00270 
<a name="l00271"></a>00271                         initCacheMap(dx_, dy_, A2);
<a name="l00272"></a>00272 
<a name="l00273"></a>00273                         <span class="comment">// --------------</span>
<a name="l00274"></a>00274                         IplImage *src = image, *dst = image;
<a name="l00275"></a>00275  
<a name="l00276"></a>00276                         cvRemap(src, dst, dx_, dy_, CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS, cvScalarAll(0));
<a name="l00277"></a>00277                         <a class="code" href="classQVImage.html">QVImage&lt;uChar, 1&gt;</a> outputImage = <a class="code" href="classQVImage.html">QVImage&lt;uChar, 1&gt;</a>(dst);
<a name="l00278"></a>00278 
<a name="l00279"></a>00279                         cvReleaseImage(&amp;dx_);
<a name="l00280"></a>00280                         cvReleaseImage(&amp;dy_);
<a name="l00281"></a>00281                         cvReleaseImage(&amp;src);
<a name="l00282"></a>00282                         cvReleaseImage(&amp;dst);
<a name="l00283"></a>00283 
<a name="l00284"></a>00284                         <span class="keywordflow">return</span> outputImage;
<a name="l00285"></a>00285                         }
<a name="l00286"></a>00286         };
<a name="l00287"></a>00287 
<a name="l00288"></a>00288 QHash&lt;QV3DPointF, QPointF&gt; detectBoard(<span class="keyword">const</span> <a class="code" href="classQVImage.html">QVImage&lt;uChar, 3&gt;</a> &amp;actualImage, <span class="keyword">const</span> <span class="keywordtype">int</span> board_w = 6, <span class="keyword">const</span> <span class="keywordtype">int</span> board_h = 9)
<a name="l00289"></a>00289         {
<a name="l00290"></a>00290         <span class="keyword">const</span> <span class="keywordtype">int</span> board_n = board_w * board_h;
<a name="l00291"></a>00291         <span class="keyword">const</span> CvSize board_sz = cvSize(board_w, board_h);
<a name="l00292"></a>00292         CvPoint2D32f* corners = <span class="keyword">new</span> CvPoint2D32f[ board_n ];
<a name="l00293"></a>00293 
<a name="l00294"></a>00294         IplImage *image = actualImage;
<a name="l00295"></a>00295         IplImage *gray_image = cvCreateImage(cvGetSize(image), 8, 1);
<a name="l00296"></a>00296 
<a name="l00297"></a>00297         CvSize image_sz = cvGetSize(image);
<a name="l00298"></a>00298 
<a name="l00299"></a>00299         <span class="keywordtype">int</span> corner_count, found = cvFindChessboardCorners(
<a name="l00300"></a>00300                                                 image, board_sz, corners, &amp;corner_count,
<a name="l00301"></a>00301                                                 CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_FILTER_QUADS);
<a name="l00302"></a>00302         
<a name="l00303"></a>00303         <span class="comment">//Get Subpixel accuracy on those corners</span>
<a name="l00304"></a>00304         cvCvtColor(image, gray_image, CV_BGR2GRAY);
<a name="l00305"></a>00305         cvFindCornerSubPix(     gray_image, corners, corner_count, cvSize(11,11),cvSize(-1,-1),
<a name="l00306"></a>00306                                 cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 30, 0.1));
<a name="l00307"></a>00307 
<a name="l00308"></a>00308         cvReleaseImage(&amp;image);
<a name="l00309"></a>00309         cvReleaseImage(&amp;gray_image);
<a name="l00310"></a>00310 
<a name="l00311"></a>00311         QHash&lt;QV3DPointF, QPointF&gt; boardCorners;
<a name="l00312"></a>00312         <span class="keywordflow">if</span>(corner_count == board_n)
<a name="l00313"></a>00313                 <span class="keywordflow">for</span>(<span class="keywordtype">int</span> j=0; j&lt;board_n; ++j)
<a name="l00314"></a>00314                         boardCorners[<a class="code" href="classQV3DPointF.html" title="3D point representation">QV3DPointF</a>(j/board_w, j%board_w, 0.0f)] = QPointF(corners[j].x, corners[j].y);
<a name="l00315"></a>00315 
<a name="l00316"></a>00316         <span class="keyword">delete</span> corners;
<a name="l00317"></a>00317         <span class="keywordflow">return</span> boardCorners;
<a name="l00318"></a>00318         }
<a name="l00319"></a>00319 
<a name="l00320"></a>00320 CameraCalibration calibrateIntrinsicsFrom3DTo2DCorrespondences(<span class="keyword">const</span> QList&lt; QHash&lt;QV3DPointF, QPointF&gt; &gt; &amp;pointCorrespondences, <span class="keyword">const</span> <span class="keywordtype">int</span> cols, <span class="keyword">const</span> <span class="keywordtype">int</span> rows)
<a name="l00321"></a>00321         {
<a name="l00322"></a>00322         <span class="comment">// Get total number of points</span>
<a name="l00323"></a>00323         <span class="keywordtype">int</span> num_points = 0;
<a name="l00324"></a>00324         <span class="keywordflow">for</span>(<span class="keywordtype">int</span> i = 0, index = 0; i &lt; pointCorrespondences.size(); i++)
<a name="l00325"></a>00325                 num_points += pointCorrespondences[index].count();
<a name="l00326"></a>00326 
<a name="l00327"></a>00327         <span class="comment">// Create 3D and 2D point lists</span>
<a name="l00328"></a>00328         CvMat* object_points  = cvCreateMat(num_points,3,CV_32FC1);
<a name="l00329"></a>00329         CvMat* image_points   = cvCreateMat(num_points,2,CV_32FC1);
<a name="l00330"></a>00330         CvMat* point_counts   = cvCreateMat(pointCorrespondences.size(),1,CV_32SC1);
<a name="l00331"></a>00331 
<a name="l00332"></a>00332         <span class="comment">// TRANSFER THE POINTS INTO THE CORRECT SIZE MATRICES</span>
<a name="l00333"></a>00333         <span class="keywordflow">for</span>(<span class="keywordtype">int</span> i = 0, index = 0; i &lt; pointCorrespondences.size(); i++)
<a name="l00334"></a>00334                 {
<a name="l00335"></a>00335                 <span class="keywordflow">foreach</span>(<a class="code" href="classQV3DPointF.html" title="3D point representation">QV3DPointF</a> point3D, pointCorrespondences[i].keys())
<a name="l00336"></a>00336                         {
<a name="l00337"></a>00337                         CV_MAT_ELEM( *image_points, <span class="keywordtype">float</span>, index, 0)    = pointCorrespondences[i][point3D].x();
<a name="l00338"></a>00338                         CV_MAT_ELEM( *image_points, <span class="keywordtype">float</span>, index, 1)    = pointCorrespondences[i][point3D].y();
<a name="l00339"></a>00339                         CV_MAT_ELEM( *object_points, <span class="keywordtype">float</span>, index, 0)   = point3D.<a class="code" href="classQV3DPointF.html#aab1c8e4380b126607771339778a83a1e" title="Gets the value for the first coordinate of the 3D point.">x</a>();
<a name="l00340"></a>00340                         CV_MAT_ELEM( *object_points, <span class="keywordtype">float</span>, index, 1)   = point3D.<a class="code" href="classQV3DPointF.html#ab3999406794a8d4afa0718af691b8920" title="Gets the value for the second coordinate of the 3D point.">y</a>();
<a name="l00341"></a>00341                         CV_MAT_ELEM( *object_points, <span class="keywordtype">float</span>, index, 2)   = point3D.<a class="code" href="classQV3DPointF.html#aba286a7e040358ecbffce7c4566cdd8d" title="Gets the value for the third coordinate of the 3D point.">z</a>();
<a name="l00342"></a>00342 
<a name="l00343"></a>00343                         index++;
<a name="l00344"></a>00344                         }
<a name="l00345"></a>00345                 CV_MAT_ELEM(*point_counts, <span class="keywordtype">int</span>, i, 0) = pointCorrespondences[i].count();
<a name="l00346"></a>00346                 }
<a name="l00347"></a>00347 
<a name="l00348"></a>00348         <span class="comment">// Create intrinsic and distortion coefficient matrices</span>
<a name="l00349"></a>00349         CvMat* intrinsic_matrix  = cvCreateMat(3,3,CV_32FC1);
<a name="l00350"></a>00350         CvMat* distortion_coeffs = cvCreateMat(4,1,CV_32FC1);
<a name="l00351"></a>00351 
<a name="l00352"></a>00352         CV_MAT_ELEM( *intrinsic_matrix, <span class="keywordtype">float</span>, 0, 0 ) = 1.0f;
<a name="l00353"></a>00353         CV_MAT_ELEM( *intrinsic_matrix, <span class="keywordtype">float</span>, 1, 1 ) = 1.0f;
<a name="l00354"></a>00354 
<a name="l00355"></a>00355         <span class="comment">// Calibrate</span>
<a name="l00356"></a>00356         cvCalibrateCamera2(object_points, image_points, point_counts, cvSize(cols,rows), intrinsic_matrix, distortion_coeffs, NULL, NULL,0);
<a name="l00357"></a>00357 
<a name="l00358"></a>00358         <span class="comment">// Create calibration object</span>
<a name="l00359"></a>00359         CameraCalibration result = CameraCalibration(cols, rows, intrinsic_matrix, distortion_coeffs);
<a name="l00360"></a>00360 
<a name="l00361"></a>00361         <span class="comment">// Release data</span>
<a name="l00362"></a>00362         cvReleaseMat(&amp;object_points);
<a name="l00363"></a>00363         cvReleaseMat(&amp;image_points);
<a name="l00364"></a>00364         cvReleaseMat(&amp;point_counts);
<a name="l00365"></a>00365         cvReleaseMat(&amp;intrinsic_matrix);
<a name="l00366"></a>00366         cvReleaseMat(&amp;distortion_coeffs);
<a name="l00367"></a>00367 
<a name="l00368"></a>00368         <span class="keywordflow">return</span> result;
<a name="l00369"></a>00369         }
<a name="l00370"></a>00370 
<a name="l00371"></a>00371 <span class="keyword">class </span>CameraCalibratorBlock: <span class="keyword">public</span> <a class="code" href="classQVProcessingBlock.html" title="Base class for Block threads.">QVProcessingBlock</a>
<a name="l00372"></a>00372         {
<a name="l00373"></a>00373         <span class="keyword">private</span>:
<a name="l00374"></a>00374                 <a class="code" href="classQVImage.html">QVImage&lt;uChar, 3&gt;</a> actualImage;
<a name="l00375"></a>00375 
<a name="l00376"></a>00376                 QList&lt; QHash&lt;QV3DPointF, QPointF&gt; &gt; grabbedBoards;
<a name="l00377"></a>00377 
<a name="l00378"></a>00378                 CameraCalibration calibration;
<a name="l00379"></a>00379 
<a name="l00380"></a>00380         <span class="keyword">public</span>:
<a name="l00381"></a>00381                 CameraCalibratorBlock(QString name): <a class="code" href="classQVProcessingBlock.html" title="Base class for Block threads.">QVProcessingBlock</a>(name)
<a name="l00382"></a>00382                         {
<a name="l00383"></a>00383                         addProperty&lt; QVImage&lt;uChar,3&gt; &gt;(<span class="stringliteral">&quot;Input image&quot;</span>, inputFlag|outputFlag);
<a name="l00384"></a>00384                         addProperty&lt; QVImage&lt;uChar,3&gt; &gt;(<span class="stringliteral">&quot;Output image&quot;</span>, outputFlag);
<a name="l00385"></a>00385                         addProperty&lt; QString &gt;(<span class="stringliteral">&quot;Camera file name&quot;</span>, inputFlag|outputFlag, <span class="stringliteral">&quot;calibrated.camera&quot;</span>);
<a name="l00386"></a>00386 
<a name="l00387"></a>00387                         addProperty&lt; QList&lt;QPointF&gt; &gt;(<span class="stringliteral">&quot;Board corners&quot;</span>, outputFlag);
<a name="l00388"></a>00388                         <a class="code" href="classQVProcessingBlock.html#a26a8c3ab6758620d7cb328f4dd60b860" title="Adds a trigger to the block.">addTrigger</a>(<span class="stringliteral">&quot;Grab chessboard&quot;</span>);
<a name="l00389"></a>00389                         <a class="code" href="classQVProcessingBlock.html#a26a8c3ab6758620d7cb328f4dd60b860" title="Adds a trigger to the block.">addTrigger</a>(<span class="stringliteral">&quot;Calibrate&quot;</span>);
<a name="l00390"></a>00390 
<a name="l00391"></a>00391                         <span class="keywordflow">if</span> (calibration.loadFromFile(getPropertyValue&lt; QString &gt;(<span class="stringliteral">&quot;Camera file name&quot;</span>)))
<a name="l00392"></a>00392                                 std::cout &lt;&lt; <span class="stringliteral">&quot;Camera loaded&quot;</span> &lt;&lt; std::endl;
<a name="l00393"></a>00393                         <span class="keywordflow">else</span>
<a name="l00394"></a>00394                                 std::cout &lt;&lt; <span class="stringliteral">&quot;Could not load camera&quot;</span> &lt;&lt; std::endl;
<a name="l00395"></a>00395                         }
<a name="l00396"></a>00396 
<a name="l00397"></a>00397                 <span class="keywordtype">void</span> <a class="code" href="classQVProcessingBlock.html#adb13844954356bd9ed1bfbe97d731095" title="Process trigger activations in the block.">processTrigger</a>(<span class="keyword">const</span> QString triggerName)
<a name="l00398"></a>00398                         {
<a name="l00399"></a>00399                         <span class="keywordflow">if</span> (triggerName == <span class="stringliteral">&quot;Grab chessboard&quot;</span>)
<a name="l00400"></a>00400                                 {
<a name="l00401"></a>00401                                 <span class="keyword">const</span> QHash&lt;QV3DPointF, QPointF&gt; grabbedBoard = detectBoard(actualImage);
<a name="l00402"></a>00402                                 <span class="keywordflow">if</span> (grabbedBoard.count() &gt; 0)
<a name="l00403"></a>00403                                         {
<a name="l00404"></a>00404                                         grabbedBoards &lt;&lt; grabbedBoard;
<a name="l00405"></a>00405                                         <a class="code" href="group__qvip.html#ga77ad534a38a3c6e3de5607c07cc0e999" title="Write the content of a QVImage (RGB) object in an image file.">writeQVImageToFile</a>(     QString(<span class="stringliteral">&quot;temp/frame-&quot;</span>) + QString::number(<a class="code" href="classQVProcessingBlock.html#a95c56bae078a84bf689b7ee8073bcf7c" title="Function to obtain the number of iteration the block has performed.">getIteration</a>()).QString::rightJustified(8, <span class="charliteral">&#39;0&#39;</span>) + <span class="stringliteral">&quot;.png&quot;</span>,
<a name="l00406"></a>00406                                                                 actualImage);
<a name="l00407"></a>00407                                         }
<a name="l00408"></a>00408                                 std::cout &lt;&lt; <span class="stringliteral">&quot;Captured &quot;</span> &lt;&lt; grabbedBoards.size() &lt;&lt; <span class="stringliteral">&quot; boards&quot;</span>&lt;&lt; std::endl;
<a name="l00409"></a>00409                                 }
<a name="l00410"></a>00410                         <span class="keywordflow">else</span> <span class="keywordflow">if</span> (triggerName == <span class="stringliteral">&quot;Calibrate&quot;</span>)
<a name="l00411"></a>00411                                 {
<a name="l00412"></a>00412                                 std::cout &lt;&lt; <span class="stringliteral">&quot;Proceeding to camera calibration.&quot;</span> &lt;&lt; std::endl;
<a name="l00413"></a>00413                                 calibration = calibrateIntrinsicsFrom3DTo2DCorrespondences(grabbedBoards, 320, 240);
<a name="l00414"></a>00414 
<a name="l00415"></a>00415                                 <span class="comment">// ---------------------------------</span>
<a name="l00416"></a>00416                                 <span class="comment">/*for(int i = 0; i &lt; grabbedBoards.size(); i++)</span>
<a name="l00417"></a>00417 <span class="comment">                                        foreach(QV3DPointF point3D, grabbedBoards[i].keys())</span>
<a name="l00418"></a>00418 <span class="comment">                                                {</span>
<a name="l00419"></a>00419 <span class="comment">                                                const QPointF p = grabbedBoards[i][point3D];</span>
<a name="l00420"></a>00420 <span class="comment">                                                grabbedBoards[i][point3D] = calibration.map(p.x(), p.y());</span>
<a name="l00421"></a>00421 <span class="comment">                                                }</span>
<a name="l00422"></a>00422 <span class="comment"></span>
<a name="l00423"></a>00423 <span class="comment">                                CameraCalibration calibration2 = calibrateIntrinsicsFrom3DTo2DCorrespondences(grabbedBoards, 320, 240);</span>
<a name="l00424"></a>00424 <span class="comment"></span>
<a name="l00425"></a>00425 <span class="comment">                                std::cout &lt;&lt; &quot;K 1 = &quot; &lt;&lt; calibration.K &lt;&lt; std::endl;</span>
<a name="l00426"></a>00426 <span class="comment">                                std::cout &lt;&lt; &quot;dist 1 = &quot; &lt;&lt; calibration.distortionCoeffs &lt;&lt; std::endl;</span>
<a name="l00427"></a>00427 <span class="comment">                                std::cout &lt;&lt; &quot;K 2 = &quot; &lt;&lt; calibration2.K &lt;&lt; std::endl;</span>
<a name="l00428"></a>00428 <span class="comment">                                std::cout &lt;&lt; &quot;dist 2 = &quot; &lt;&lt; calibration2.distortionCoeffs &lt;&lt; std::endl;*/</span>
<a name="l00429"></a>00429 
<a name="l00430"></a>00430                                 <span class="comment">// ---------------------------------</span>
<a name="l00431"></a>00431 
<a name="l00432"></a>00432                                 <span class="keywordflow">if</span> (calibration.saveToFile(<span class="stringliteral">&quot;calibrated.camera&quot;</span>))
<a name="l00433"></a>00433                                         std::cout &lt;&lt; <span class="stringliteral">&quot;Camera calibrated and stored.&quot;</span> &lt;&lt; std::endl;
<a name="l00434"></a>00434                                 <span class="keywordflow">else</span>
<a name="l00435"></a>00435                                         std::cout &lt;&lt; <span class="stringliteral">&quot;Error storing camera.&quot;</span> &lt;&lt; std::endl;
<a name="l00436"></a>00436                                 }
<a name="l00437"></a>00437                         std::cout &lt;&lt; <span class="stringliteral">&quot;End of trigger processing&quot;</span> &lt;&lt; std::endl;
<a name="l00438"></a>00438                         }
<a name="l00439"></a>00439 
<a name="l00440"></a>00440                 <span class="keywordtype">void</span> <a class="code" href="classQVProcessingBlock.html#a0283c799776e0c938538de0b0ae6b463" title="Function to be defined in subclasses with processing code.">iterate</a>()
<a name="l00441"></a>00441                         {
<a name="l00442"></a>00442                         actualImage = getPropertyValue&lt;QVImage&lt;uChar, 3&gt; &gt;(<span class="stringliteral">&quot;Input image&quot;</span>);
<a name="l00443"></a>00443 
<a name="l00444"></a>00444                         <span class="keyword">const</span> QHash&lt;QV3DPointF, QPointF&gt; boardCorners = detectBoard(actualImage);
<a name="l00445"></a>00445                         setPropertyValue&lt; QList&lt;QPointF&gt; &gt;(<span class="stringliteral">&quot;Board corners&quot;</span>, boardCorners.values());
<a name="l00446"></a>00446 
<a name="l00447"></a>00447                         <span class="keywordflow">if</span> (not calibration.inited())
<a name="l00448"></a>00448                                 <span class="keywordflow">return</span>;
<a name="l00449"></a>00449 
<a name="l00450"></a>00450                         <span class="keywordflow">if</span> (boardCorners.count() &gt; 0)
<a name="l00451"></a>00451                                 {
<a name="l00452"></a>00452                                 QList&lt;QPointFMatching&gt; matchings;
<a name="l00453"></a>00453                                 <span class="keywordflow">foreach</span>(<a class="code" href="classQV3DPointF.html" title="3D point representation">QV3DPointF</a> point3D, boardCorners.keys())
<a name="l00454"></a>00454                                         {
<a name="l00455"></a>00455                                         <span class="keyword">const</span> QPointF p = boardCorners[point3D];
<a name="l00456"></a>00456                                         matchings &lt;&lt; <a class="code" href="group__qvmath.html#ga818fe0c689af956cd14431148c879718">QPointFMatching</a>(QPointF(point3D.<a class="code" href="classQV3DPointF.html#aab1c8e4380b126607771339778a83a1e" title="Gets the value for the first coordinate of the 3D point.">x</a>(), point3D.<a class="code" href="classQV3DPointF.html#ab3999406794a8d4afa0718af691b8920" title="Gets the value for the second coordinate of the 3D point.">y</a>()), <a class="code" href="group__qvprojectivegeometry.html#ga305b04da4d0035c3b4de07ff381b9e1c" title="Maps a point using an homography.">applyHomography</a>(calibration.Kinv,p));
<a name="l00457"></a>00457                                         }
<a name="l00458"></a>00458                                 <span class="keyword">const</span> <a class="code" href="classQVMatrix.html" title="Implementation of numerical matrices.">QVMatrix</a>  H = <a class="code" href="group__qvprojectivegeometry.html#ga72b520d418b7835458269a7d803c6668" title="Obtains a planar homography from a list of point correspondences.">computeProjectiveHomography</a>(matchings),
<a name="l00459"></a>00459                                                 errorM = H.<a class="code" href="classQVMatrix.html#a2f87710c9d8ae4b07b03605daea3782e" title="Change the order of the indexes in the matrix.">transpose</a>()*H,
<a name="l00460"></a>00460                                                 normalizedErrorM = errorM * (2.0 / (errorM(0,0) + errorM(1,1)));
<a name="l00461"></a>00461 
<a name="l00462"></a>00462                                 <span class="keyword">const</span> <span class="keywordtype">double</span> a = errorM(0,0), b = errorM(0,1), c = errorM(1,0), d = errorM(1,1);
<a name="l00463"></a>00463 
<a name="l00464"></a>00464                                 std::cout &lt;&lt; ( ABS(1-normalizedErrorM(0,0)) + ABS(1- normalizedErrorM(1,1)) + 2*ABS(normalizedErrorM(1,0)) ) &lt;&lt; std::endl;
<a name="l00465"></a>00465                                 std::cout &lt;&lt; <span class="stringliteral">&quot;H^t * H = &quot;</span> &lt;&lt; normalizedErrorM &lt;&lt; std::endl;
<a name="l00466"></a>00466                                 }
<a name="l00467"></a>00467 
<a name="l00468"></a>00468                         <span class="comment">//setPropertyValue&lt; QVImage&lt;uChar, 3&gt; &gt;(&quot;Output image&quot;, calibration.radialUndistort(actualImage));</span>
<a name="l00469"></a>00469                         }
<a name="l00470"></a>00470         };
<a name="l00471"></a>00471 
<a name="l00472"></a>00472 <span class="preprocessor">#include &lt;QVVector&gt;</span>
<a name="l00473"></a>00473 <span class="preprocessor">#include &lt;QVMatrix&gt;</span>
<a name="l00474"></a>00474 <span class="keywordtype">int</span> main(<span class="keywordtype">int</span> argc, <span class="keywordtype">char</span> *argv[])
<a name="l00475"></a>00475         {
<a name="l00476"></a>00476         <a class="code" href="classQVApplication.html" title="Main class for QVision applications.">QVApplication</a> app(argc, argv, <span class="stringliteral">&quot;Example program for QVision library. Displays the contents of a video source.&quot;</span>);
<a name="l00477"></a>00477 
<a name="l00478"></a>00478         <a class="code" href="classQVVideoReaderBlock.html" title="This is a generic video input processing block for the QVision architecture.">QVVideoReaderBlock</a> camera(<span class="stringliteral">&quot;Video&quot;</span>);
<a name="l00479"></a>00479 
<a name="l00480"></a>00480         CameraCalibratorBlock player(<span class="stringliteral">&quot;Video player&quot;</span>);
<a name="l00481"></a>00481         camera.linkProperty(&amp;player,<span class="stringliteral">&quot;Input image&quot;</span>);
<a name="l00482"></a>00482 
<a name="l00483"></a>00483         <a class="code" href="classQVDefaultGUI.html" title="Main user interface widget for QVision applications.">QVDefaultGUI</a> interface;
<a name="l00484"></a>00484 
<a name="l00485"></a>00485         <a class="code" href="classQVImageCanvas.html" title="Display widget for QVImage objects and other data types.">QVImageCanvas</a> inputImageCanvas(<span class="stringliteral">&quot;Input image&quot;</span>);
<a name="l00486"></a>00486         player.linkProperty(<span class="stringliteral">&quot;Input image&quot;</span>, inputImageCanvas);
<a name="l00487"></a>00487         player.linkProperty(<span class="stringliteral">&quot;Board corners&quot;</span>, inputImageCanvas);
<a name="l00488"></a>00488 
<a name="l00489"></a>00489         <a class="code" href="classQVImageCanvas.html" title="Display widget for QVImage objects and other data types.">QVImageCanvas</a> outputImageCanvas(<span class="stringliteral">&quot;Output image&quot;</span>);
<a name="l00490"></a>00490         player.linkProperty(<span class="stringliteral">&quot;Output image&quot;</span>, outputImageCanvas);
<a name="l00491"></a>00491 
<a name="l00492"></a>00492 
<a name="l00493"></a>00493         <span class="keywordflow">return</span> app.exec();
<a name="l00494"></a>00494         }
<a name="l00495"></a>00495 <span class="preprocessor">#endif  // DOXYGEN_IGNORE_THIS</span>
<a name="l00496"></a>00496 <span class="preprocessor"></span>
</pre></div></div>
</td></tr></table>

<br /><hr><br />
<center><a href="http://perception.inf.um.es/QVision">QVision framework</a>.
<a href="http://perception.inf.um.es">PARP research group</a>.
Copyright &copy; 2007, 2008, 2009, 2010, 2011.</center>
<br />
</body>
</html>
